﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Text;
using System.Threading;
using Porownywarka.Interfejsy;
using Porownywarka.Sortowanie;

namespace Porownywarka
{
    public class Porownywarka<T> where T: IComparable<T>
    {
        //public Data Wyniki { get; private set; }
        public ISortMethod<T>[] MetodySortuajce { get; private set; }
        public int KwantCzasu { get; private set; }
        public List<AsyncObservableCollection<KeyValuePair<string, int>>> ListaKolekcji { get; private set; }
        public bool Paused { get; private set; }
        public event MyEventHandler Finished;

        public int RozmiarDanych { get; set; }
        public T[] Dane { get; private set; }
        
        private T[] posortowaneDane;
        private List<Thread> threadPool;
        private bool start;
        private bool anyRunning = true;

        private bool stop;
        private bool sortedDataFresh;

        private object lockObj = new object();

         protected virtual void OnMyEvent(MyEventArgs e)
         {
             Finished(this, e);
         }

        private void SortData()
        {
            posortowaneDane = new QuickSort<T>().Sort(Dane, new object());
            sortedDataFresh = true;
        }

        public void ChangeData(T[] dane)
        {
            Dane = dane;
            SortData();
        }

        public void Start(int kwant)
        {
            if(!sortedDataFresh)
                SortData();

            KwantCzasu = kwant;
            Porownaj();
        }

        public void Pause()
        {
            Paused = true;
        }

        public void Continue()
        {
            Paused = false;
        }

        public void Stop()
        {
            stop = true;
        }

        public Porownywarka(ISortMethod<T>[] metodySortowania, T[] dane, List<AsyncObservableCollection<KeyValuePair<string, int>>> wyniki)
        {
            MetodySortuajce = metodySortowania;
            Dane = dane;
            ListaKolekcji = wyniki;
            //Wyniki = new Data(metodySortowania.Length);
        }

        private void Work(int i)
        {
            MetodySortuajce[i].Sort(Dane, lockObj);
        }

        private void Porownaj()
        {
            int czas = 0;

            for (int i = 0; i < MetodySortuajce.Length; i++)
                ListaKolekcji[i].Add(new KeyValuePair<string, int>("0", 0));

            Action a = () =>
            {
                if (!Paused)
                {
                    if (start)
                    {
                        start = false;
                        anyRunning = false;

                        for (int i = 0; i < threadPool.Count; i++)
                        {
                            int kop = i;

                            if (threadPool[kop].IsAlive)
                            {
                                try
                                {
                                    threadPool[kop].Suspend();
                                    anyRunning = true;
                                }
                                catch
                                {
                                }
                            }
                        }

                        for (int i = 0; i < threadPool.Count; i++)
                        {
                            if(threadPool[i].IsAlive)
                            {
                                int suma2 = 0;
                                for (int j = 0; j < posortowaneDane.Length; j++)
                                    if (posortowaneDane[j].CompareTo(MetodySortuajce[i].SortedData[j]) == 0)
                                        suma2++;

                                ListaKolekcji[i].Add(new KeyValuePair<string, int>(czas.ToString(), suma2));

                                if( ListaKolekcji[i].Count > 30 )
                                {
                                    for (int j = 0; j < ListaKolekcji[i].Count; j+=3)
                                    {
                                        ListaKolekcji[i].RemoveAt(j);
                                    }
                                }

                            }

                        }
                    }
                    else
                    {
                            start = true;

                            for (int i = 0; i < threadPool.Count; i++)
                            {
                                int kop = i;

                                if (threadPool[kop].IsAlive)
                                    threadPool[kop].Resume();
                            }   
                    }


                    if (start)
                    {
                        czas += KwantCzasu;
                        Thread.Sleep(KwantCzasu);
                    }
                }
            };

            threadPool = new List<Thread>();
            for (int i = 0; i < MetodySortuajce.Length; i++)
            {
                int c = i;
                threadPool.Add(new Thread(() => { Work(c); }));
            }

            for (int i = 0; i < threadPool.Count; i++)
            {
                threadPool[i].Start();
                if (threadPool[i].IsAlive)
                {
                    try
                    {
                        threadPool[i].Suspend();
                    }
                    catch (ThreadStateException ex)
                    {
                    }
                }             
            }

            while (anyRunning && !stop)
            {
                a();
            }  
          
            OnMyEvent(new MyEventArgs());

        }

    }
}
